package com.song.service;

import com.song.domain.Order;
import com.song.domain.OrderItem;
import com.song.mapper.OrderMapper;
import com.song.mapper.MaterialMapper;
import com.song.mapper.OrderItemMapper;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class OrderService {
    private final OrderMapper mapper;
    private final MaterialMapper materialMapper;
    private final OrderItemMapper orderItemMapper;

    public OrderService(OrderMapper mapper, MaterialMapper materialMapper, OrderItemMapper orderItemMapper) {
        this.mapper = mapper;
        this.materialMapper = materialMapper;
        this.orderItemMapper = orderItemMapper;
    }

    public Order get(Long id) {
        return mapper.selectById(id);
    }

    public List<Order> list(int page, int size, String status, java.util.Date startDate, java.util.Date endDate, String customerName) {
        int offset = Math.max(page - 1, 0) * size;
        List<Order> orders = mapper.list(offset, size, normalizeStatus(status), startDate, endDate, customerName);
        for (Order o : orders) {
            if (o.getId() != null) o.setItems(orderItemMapper.listByOrderId(o.getId()));
        }
        return orders;
    }

    public int count(String status, java.util.Date startDate, java.util.Date endDate, String customerName) {
        return mapper.count(normalizeStatus(status), startDate, endDate, customerName);
    }

    public Order create(Order order) {
        order.setCreatedAt(new Date());
        if (order.getItems() != null && !order.getItems().isEmpty()) {
            validateDates(order);
            java.math.BigDecimal total = java.math.BigDecimal.ZERO;
            for (OrderItem it : order.getItems()) {
                com.song.domain.Material material = materialMapper.selectById(it.getMaterialId());
                if (material == null || Boolean.FALSE.equals(material.getActive())) {
                    throw new IllegalArgumentException("material not available");
                }
                if (it.getQuantity() == null || it.getQuantity() <= 0) {
                    throw new IllegalArgumentException("item quantity must be greater than 0");
                }
                long days = daysBetween(order.getStartDate(), order.getEndDate());
                java.math.BigDecimal itemTotal = material.getPricePerDay()
                        .multiply(java.math.BigDecimal.valueOf(days))
                        .multiply(java.math.BigDecimal.valueOf(it.getQuantity()));
                it.setPricePerDay(material.getPricePerDay());
                it.setTotalPrice(itemTotal);
                total = total.add(itemTotal);
            }
            order.setTotalPrice(total);
            order.setMaterialId(order.getItems().get(0).getMaterialId());
            order.setQuantity(order.getItems().get(0).getQuantity());
            mapper.insert(order);
            for (OrderItem it : order.getItems()) {
                it.setOrderId(order.getId());
                orderItemMapper.insert(it);
            }
            return order;
        } else {
            validateAndCompute(order);
            mapper.insert(order);
            return order;
        }
    }

    public Order update(Order order) {
        validateAndCompute(order);
        mapper.update(order);
        return order;
    }

    public void delete(Long id) {
        mapper.delete(id);
    }

    public List<Order> listAll(String status, java.util.Date startDate, java.util.Date endDate, String customerName) {
        List<Order> orders = mapper.listAll(normalizeStatus(status), startDate, endDate, customerName);
        for (Order o : orders) {
            if (o.getId() != null) o.setItems(orderItemMapper.listByOrderId(o.getId()));
        }
        return orders;
    }

    public java.math.BigDecimal sumTotal() {
        java.math.BigDecimal v = mapper.sumTotal();
        return v != null ? v : java.math.BigDecimal.ZERO;
    }

    private void validateAndCompute(Order order) {
        if (order.getQuantity() == null || order.getQuantity() <= 0) {
            throw new IllegalArgumentException("quantity must be greater than 0");
        }
        validateDates(order);
        com.song.domain.Material material = materialMapper.selectById(order.getMaterialId());
        if (material == null || Boolean.FALSE.equals(material.getActive())) {
            throw new IllegalArgumentException("material not available");
        }
        long days = daysBetween(order.getStartDate(), order.getEndDate());
        java.math.BigDecimal total = material.getPricePerDay()
                .multiply(java.math.BigDecimal.valueOf(days))
                .multiply(java.math.BigDecimal.valueOf(order.getQuantity()));
        order.setTotalPrice(total);
    }

    private void validateDates(Order order) {
        if (order.getStartDate() == null || order.getEndDate() == null) {
            throw new IllegalArgumentException("startDate and endDate are required");
        }
        if (order.getStartDate().after(order.getEndDate())) {
            throw new IllegalArgumentException("startDate must be before or equal to endDate");
        }
    }

    private long daysBetween(java.util.Date start, java.util.Date end) {
        java.time.LocalDate s = start.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
        java.time.LocalDate e = end.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
        return java.time.temporal.ChronoUnit.DAYS.between(s, e) + 1;
    }

    private String normalizeStatus(String status) {
        if (status == null) return null;
        String s = status.trim();
        if (s.isEmpty()) return null;
        if ("已结束".equals(s) || "结束".equals(s) || "COMPLETED".equalsIgnoreCase(s)) return "0";
        if ("进行中".equals(s) || "IN_PROGRESS".equalsIgnoreCase(s)) return "1";
        if ("未开始".equals(s) || "OPEN".equalsIgnoreCase(s)) return "2";
        return s;
    }
}